package cn.com.cifi.mars.web.action.goodsValueApprove;

import static java.util.stream.Collectors.toList;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.com.cifi.mars.bean.vo.price.*;
import cn.com.cifi.mars.entity.*;
import cn.com.cifi.mars.service.*;
import cn.com.cifi.mars.util.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import cn.com.cifi.mars.bean.bo.SysLogBO;
import cn.com.cifi.mars.bean.dto.VersionTypeCountDto;
import cn.com.cifi.mars.bean.vo.price.req.PriceApproveReqParam;
import cn.com.cifi.mars.bean.vo.price.req.PriceApproveWarnCancelReqParam;
import cn.com.cifi.mars.bean.vo.price.req.PriceApproveWarnSaveReqParam;
import cn.com.cifi.mars.common.base.BaseAction;
import cn.com.cifi.mars.common.bean.R;
import cn.com.cifi.mars.common.exception.MsgException;
import cn.com.cifi.mars.constant.ApprovedStateCodeEnum;
import cn.com.cifi.mars.constant.CodeEnum;
import cn.com.cifi.mars.constant.CollectTypeEnum;
import cn.com.cifi.mars.constant.HrOrgTypeEunm;
import cn.com.cifi.mars.constant.IsDeleteEnum;
import cn.com.cifi.mars.constant.IsSuccessEnum;
import cn.com.cifi.mars.constant.LogEventEnum;
import cn.com.cifi.mars.constant.LogSrcEnum;
import cn.com.cifi.mars.constant.LogTypeEnum;
import cn.com.cifi.mars.constant.ModifySourceTypeEunm;
import cn.com.cifi.mars.constant.ModuleTypeEunm;
import cn.com.cifi.mars.constant.OrgTypeEunm;
import cn.com.cifi.mars.constant.ProcessTypeEnum;
import cn.com.cifi.mars.constant.StageStatusEnum;
import cn.com.cifi.mars.constant.VersionEventEnum;
import cn.com.cifi.mars.constant.VersionStatusEnum;
import cn.com.cifi.mars.constant.VersionTypeEunm;
import cn.com.cifi.mars.constant.WhetherEnum;
import cn.com.cifi.mars.entity.common.IdmUser;
import cn.com.cifi.mars.mapper.mars.ApprovalPreviewMapper;
import cn.com.cifi.mars.mapper.mars.ProjectReturnCoefficientMapper;
import cn.com.cifi.mars.mapper.mars.SignPlanVersionMapper;
import cn.com.cifi.mars.util.json.JsonUtils;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
public class AllGoodsValueController extends BaseAction implements IAllGoodsValueController {
    @Autowired
    private ApprovalBillDetailService approvalBillDetailService;
    @Autowired
    private ProjectBasicService projectBasicService;
    @Autowired
    private SubmitApprovedProjectService submitApprovedProjectService;
    @Autowired
    private ProjectReturnCoefficientMapper returnCoefficientMapper;
    @Autowired
    private PriceVersionService priceVersionService;
    @Autowired
    private ApprovalPreviewMapper approvalPreviewMapper;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private ApprovalBillService approvalBillService;
    @Autowired
    private ApprovalVersionCompareService approvalVersionCompareService;
    @Autowired
    private FileUploadService fileUploadService;
    @Autowired
    private ApprovedRecoreViewService approvedRecoreViewService;
    @Autowired
    private SignPlanVersionMapper signPlanVersionMapper;
    @Autowired
    private SysLogService sysLogService;
    @Autowired
    private ApprovalLogService approvalLogService;
    @Autowired
    private SignPlanVersionService signPlanVersionService;
    @Autowired
    private VersionLogService versionLogService;
    @Autowired
    private StageService stageService;
    @Autowired
    private ReturnPlanVersionService returnPlanVersionService;
    @Autowired
    private ApprovalPreviewService approvalPreviewService;
    @Autowired
    private ApprovalWarningService approvalWarningService;
    @Autowired
    private ApprovalWarningSuperviseService approvalWarningSuperviseService;
    @Autowired
    private PriceVersionGroupService priceVersionGroupService;
    @Autowired
    private AllGoodsValueService allGoodsValueService;
    @Autowired
    private PriceApprovalDifferencesService priceApprovalDifferencesService;
    @Autowired
    private PriceApprovalDifferencesDetailService priceApprovalDifferencesDetailService;
    @Autowired
    private PriceApprovalDifferencesBuildService priceApprovalDifferencesBuildService;
    @Autowired
    private PriceApprovalCoreWarnService priceApprovalCoreWarnService;

    @Value("${previewUrl}")
    private String url;

    @Value("${PORTAL_SYSCODE}")
    private String sysCode;

    @Value("${PORTAL_SECRET_KEY}")
    private String secretKey;

    @Value("${view_approved_url}")
    String view_approved_url;

    /**
     * 货值审批-审批校验
     */
    @Override
    public R<Map<String, Boolean>> approvedCheck(String apiVersion, String projectId, String approvedType) {
        Map<String, Boolean> map = new HashMap<>();
        List<Integer> batchAdjustList = new ArrayList<>();
        if (StringUtils.isNotBlank(projectId)) {
            int num = submitApprovedProjectService.checkApprovedVersionIsNull(projectId);
            String validFlag = "";
            if (num == 0) {
                throw new MsgException(CodeEnum.NOT_EXIST_VERSION);
            } else {
                //存在待编制或审批中的版本，不能提交审批
                List<PriceVersion> count = submitApprovedProjectService.checkApprovedVersion(projectId);
                if (CollectionUtils.isNotEmpty(count)) {
                    throw new MsgException(CodeEnum.NOT_APPROVED);
                }
                //获取提审版本
                List<PriceVersion> priceVersionList = submitApprovedProjectService.selectApprovedProject(projectId);
                if (CollectionUtils.isEmpty(priceVersionList)) {
                    throw new MsgException(CodeEnum.APPROVED_NON_EXISTENT);
                } else {
                    for (PriceVersion version : priceVersionList) {
                        if (version.getBatchAdjust() != null && !batchAdjustList.contains(version.getBatchAdjust())) {
                            batchAdjustList.add(version.getBatchAdjust());
                        }
                        //禁用分期不能存在在途版本来发起审批
                        MdmStage mdmStage = stageService.selectById(version.getProjectfId());
                        if (mdmStage != null) {
                            String status = mdmStage.getStatus();
                            if (StringUtils.isNotEmpty(status) && status.equals(StageStatusEnum.INACTIVE.getKey())) {
                                throw new MsgException(CodeEnum.APPROVED_CHECK_ERROR);
                            }
                        }
                        validFlag = priceVersionService.priceVersionValidated(version.getId());
                    }

                    if (StrUtils.isNotEmpty(validFlag)) {
                        CodeEnum.VERSION_VALUE_ERROR.setMessage(validFlag);
                        throw new MsgException(CodeEnum.VERSION_VALUE_ERROR);
                    }
                    if (CollectionUtils.isNotEmpty(batchAdjustList)) {
                        //提审版本中即包含普调版本又包含正常版本
                        if (batchAdjustList.size() > 1) {
                            throw new MsgException(CodeEnum.PROJECT_CHECK_VERSION_ERROR);
                        }

                        if (approvedType.equals("normal_approve")) {
                            if (batchAdjustList.get(0).intValue() == 1) {
                                throw new MsgException(CodeEnum.PRICE_CHECK_VERSION_ERROR);
                            }
                        }

                        if (approvedType.equals("pt_approve")) {
                            if (batchAdjustList.get(0).intValue() == 0) {
                                throw new MsgException(CodeEnum.PRICE_CHECK_VERSION_ERROR);
                            }
                        }
                    }
                }

                //项目下发起审批的分期是否都被禁用
                List<MdmStage> stages = stageService.selectByProjectId(projectId, IsDeleteEnum.NO.getKey());
                List<String> stageStates = Optional.of(stages).orElseGet(ArrayList::new).stream().map(MdmStage::getStatus)
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(stageStates) && !stageStates.contains(StageStatusEnum.CTIVE.getKey())) {
                    throw new MsgException(CodeEnum.APPROVED_CHECK_ERROR);
                }
                map.put("result", true);
                return ok(map);
            }
        }
        return ok("请输入正确的参数");
    }

    /**
     * 货值审批-基本信息
     */
    @Override
    public R<BasicInfoVO> basicInfo(String apiVersion, String projectId, String businessKey) {
        BasicInfoVO basicInfoVO = prepareBaseInfo(businessKey, projectId);
        return ok(basicInfoVO);
    }

    private BasicInfoVO prepareBaseInfo(String businessKey, String projectId) {
        BasicInfoVO basicInfoVO = new BasicInfoVO();
        if (StringUtils.isNotBlank(businessKey)) {
            ApprovalBill approvalBill = submitApprovedProjectService.selectApprovalBillByKey(businessKey);
            projectId = approvalBill.getProjectId();
            basicInfoVO.setProjectId(projectId);
            if (approvalBill != null) {
                basicInfoVO.setInstanceId(approvalBill.getInstanceId());
                basicInfoVO.setTaskId(approvalBill.getTaskId());
                basicInfoVO.setState(approvalBill.getState());
                basicInfoVO.setDescription(approvalBill.getDescription());
                //附件查询
                String billId = approvalBill.getId();
                List<UploadFile> fileList = fileUploadService.selectFileByBusinessKey(billId);
                List<FilePreviewVO> previewList = new ArrayList<>();
                for (UploadFile uploadFile : fileList) {
                    FilePreviewVO previewVO = new FilePreviewVO();
                    previewVO.setFileId(uploadFile.getId());
                    previewVO.setFileName(uploadFile.getOriginalFileName());
                    previewVO.setFilePath(uploadFile.getFileStoreAddress());
                    previewVO.setPreviewUrl(uploadFile.getPreViewUrl());
                    previewList.add(previewVO);
                }
                basicInfoVO.setFiles(previewList);
                //查看审批URL
                String encode = prepareReviewUrl(approvalBill);
                basicInfoVO.setReviewUrl(view_approved_url + encode);
            }
        } else {
            //根据projectId查询最新审批的状态
            ApprovalBill approvalBill = submitApprovedProjectService.selectApprovalBillByProjectId(projectId, ProcessTypeEnum.PRICE_MANAGEMENT.getKey());
            if (null != approvalBill) {
                String state = approvalBill.getState();
                if (!state.equals(ApprovedStateCodeEnum.DELETE.getKey()) &&
                        !state.equals(ApprovedStateCodeEnum.ENDFLOW.getKey()) &&
                        !state.equals(ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey())) {
                    //查询审批说明
                    String description = approvalBill.getDescription();
                    basicInfoVO.setDescription(description);
                    //附件查询
                    String billId = approvalBill.getId();
                    List<UploadFile> fileList = fileUploadService.selectFileByBusinessKey(billId);
                    List<FilePreviewVO> previewList = new ArrayList<>();
                    for (UploadFile uploadFile : fileList) {
                        FilePreviewVO previewVO = new FilePreviewVO();
                        previewVO.setFileId(uploadFile.getId());
                        previewVO.setFileName(uploadFile.getOriginalFileName());
                        previewVO.setFilePath(uploadFile.getFileStoreAddress());
                        previewVO.setPreviewUrl(uploadFile.getPreViewUrl());
                        previewList.add(previewVO);
                    }
                    basicInfoVO.setFiles(previewList);
                    basicInfoVO.setProjectId(projectId);
                    basicInfoVO.setInstanceId(approvalBill.getInstanceId());
                    basicInfoVO.setTaskId(approvalBill.getTaskId());
                    basicInfoVO.setState(state);
                    //查看审批URL
                    String encode = prepareReviewUrl(approvalBill);
                    basicInfoVO.setReviewUrl(view_approved_url + encode);
                }
            }
        }

        //项目信息
        MdmProject mdmProject = projectService.selectByProjectId(projectId, IsDeleteEnum.NO.getKey());
        if (mdmProject != null) {
            basicInfoVO.setProjectCode(mdmProject.getProjectCode());
            basicInfoVO.setProjectName(mdmProject.getProjectName());
        }

        //查询区域
        List<String> str = projectBasicService.selectFullPath(projectId);
        String orgName = projectBasicService.selectRegionName(str, HrOrgTypeEunm.ORG_20.getKey());
        basicInfoVO.setArea(orgName);

        //查询权益比例
        MdmProjectPatner projectPatner = projectBasicService.selecteQuityRatio(projectId);
        if (projectPatner != null) {
            if (projectPatner.getEquityRatio() != null) {
                basicInfoVO.setQuityRatio(projectPatner.getEquityRatio().toString());
            }
        }

        //获取提审版本
        List<PriceVersion> priceVersionList = submitApprovedProjectService.selectApprovedProject(projectId);
        if (CollectionUtils.isNotEmpty(priceVersionList)) {
            if (priceVersionList.get(0).getBatchAdjust().intValue() == 0) {
                basicInfoVO.setApprovedType("normal_approve");
            } else {
                basicInfoVO.setApprovedType("pt_approve");
            }
        }

        //查询货值差异是否可以导出excel
        boolean b1 = priceApprovalDifferencesService.selectOne(businessKey);
        basicInfoVO.setDifferenceExportStatus(b1);

        //查询调价信息是否可以导出excel
        boolean b2 = priceApprovalCoreWarnService.selectOne(businessKey);
        basicInfoVO.setWarnInfoExportStatus(b2);

        return basicInfoVO;
    }

    private String prepareReviewUrl(ApprovalBill approvalBill) {
        String encode = null;
        JSONObject jsonObj = new JSONObject();
        if (StrUtils.isNotEmpty(approvalBill.getTaskId())) {
            jsonObj.put("proInstId", approvalBill.getInstanceId());
            jsonObj.put("taskId", approvalBill.getTaskId());
            try {
                encode = Base64.getEncoder().encodeToString(jsonObj.toString().getBytes("utf-8"));
            } catch (UnsupportedEncodingException e) {
                log.error("###### errorMsg: ", e);
            }
        } else {
            jsonObj.put("proInstId", approvalBill.getInstanceId());
            try {
                encode = Base64.getEncoder().encodeToString(jsonObj.toString().getBytes("utf-8"));
            } catch (UnsupportedEncodingException e) {
                log.error("###### errorMsg: ", e);
            }
        }
        return encode;
    }

    /**
     * 货值审批-基本信息（APP）
     */
    @Override
    public R<BasicInfoVO> appBasicInfo(String apiVersion, String projectId, String businessKey) {
        return basicInfo(apiVersion, projectId, businessKey);
    }

    /**
     * 货值审批-本次填报版本
     */
    @Override
    public R<Map<String, String>> approvedInfo(String apiVersion, String projectId, String businessKey) {
        Map<String, String> map = new TreeMap<>();
        if (StringUtils.isNotBlank(businessKey)) {
            ApprovalBill approvalBill = submitApprovedProjectService.selectApprovalBillByKey(businessKey);
            //审批通过后再查看从t_approval_bill_detail查询
            if (approvalBill.getState().equals(ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey()) ||
                    approvalBill.getState().equals(ApprovedStateCodeEnum.APPROVAL.getKey())) {
                //审批通过时间
                String lastDate = "";
                if (approvalBill.getState().equals(ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey())) {
                    lastDate = LocalDateTimeUtils.formatTime(approvalBill.getUpdateTime(), DateUtils.DATE_KEY_SMALL_STR);
                }
                List<ApprovalBillDetail> approvalBillDetails = approvalBillDetailService.selectApprovalBillDetail(businessKey);
                for (ApprovalBillDetail approvalBillDetail : approvalBillDetails) {
                    String versionId = approvalBillDetail.getVersionId();
                    PriceVersion priceVersion = priceVersionService.selectByVersionId(versionId);
                    String stageName = approvalBillDetail.getStageName();
                    String versionName = prepareVersionName(priceVersion, lastDate);
                    map.put(stageName, versionName);
                }
                return ok(map);
            } else {
                projectId = approvalBill.getProjectId();
            }
        }

        List<PriceVersion> priceVersionList = submitApprovedProjectService.selectApprovedProject(projectId);
        if (CollectionUtils.isNotEmpty(priceVersionList)) {
            for (PriceVersion priceVersion : priceVersionList) {
                //如果分期已被禁用，则不展示
                String projectfId = priceVersion.getProjectfId();
                if (submitApprovedProjectService.stageStateInfo(projectfId)) continue;

                String stageName = priceVersion.getStageName();
                String lastDate = "";
                if (priceVersion.getVersionState().equals(ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey())) {
                    if (priceVersion.getUpdateTime() != null) {
                        lastDate = LocalDateTimeUtils.formatTime(priceVersion.getUpdateTime(), DateUtils.DATE_KEY_SMALL_STR);
                    } else {
                        lastDate = LocalDateTimeUtils.formatTime(priceVersion.getCreateTime(), DateUtils.DATE_KEY_SMALL_STR);
                    }
                }
                String versionName = prepareVersionName(priceVersion, lastDate);
                map.put(stageName, versionName);
            }
            return ok(map);
        }

        return ok(map);
    }

    private String prepareVersionName(PriceVersion priceVersion, String lastDate) {
        String versionName = "";
        String versionType = priceVersion.getVersionType();
        Integer batchAdjust = priceVersion.getBatchAdjust();
        String versionTypeName = VersionTypeEunm.getValueByKey(versionType);
        String vesionNum = priceVersion.getVersionNum();
        if (versionType.equals(VersionTypeEunm.INVESTMENT.getKey())) {
            Integer isAssessmentVersion = priceVersion.getIsAssessmentVersion();
            if (StrUtils.isEmpty(lastDate)) {
                if (isAssessmentVersion != null && isAssessmentVersion.intValue() == 1) {
                    versionName = versionTypeName + vesionNum + "（考核版）";
                } else {
                    versionName = versionTypeName + vesionNum;
                }
            } else {
                if (isAssessmentVersion != null && isAssessmentVersion.intValue() == 1) {
                    versionName = versionTypeName + vesionNum + "-" + lastDate + "（考核版）";
                } else {
                    versionName = versionTypeName + vesionNum + "-" + lastDate;
                }
            }
        } else if (versionType.equals(VersionTypeEunm.WARPLAN.getKey()) || versionType.equals(VersionTypeEunm.GETPRICE.getKey())) {
            if (StrUtils.isEmpty(lastDate)) {
                versionName = versionTypeName + vesionNum;
            } else {
                versionName = versionTypeName + vesionNum + "-" + lastDate;
            }
        } else {
            String batch = batchAdjust != null && batchAdjust.intValue() == 1 ? "(普调版)" : "";
            String affiliationMonth = LocalDateTimeUtils.formatDate(priceVersion.getAscriptionDate(), DateUtils.DATE_KEY_SMALL);
            if (StrUtils.isEmpty(lastDate)) {
                versionName = affiliationMonth + "月动态版" + vesionNum + batch;
            } else {
                versionName = affiliationMonth + "月动态版" + vesionNum + "-" + batch + lastDate;
            }
        }
        return versionName;
    }


    /**
     * 货值审批-本次填报版本（APP）
     */
    @Override
    public R<Map<String, String>> appApprovedInfo(String apiVersion, String projectId, String businessKey) {
        return approvedInfo(apiVersion, projectId, businessKey);
    }

    /**
     * 货值审批-定调价预警信息
     */
    @Override
    public R warnInfo(String apiVersion, String projectId, String businessKey) {
        PriceApproveWarnInfoVO vo = approvalPreviewService.getWarnInfo(projectId, businessKey);
        return ok(vo);
    }

    /**
     * 货值审批-全盘货值差异概览
     */
    @Override
    public R<List<DifferenceReviewVersionVO>> newAllgoodsValueReview(String apiVersion, String projectId, String businessKey) {
        if (StrUtils.isEmpty(businessKey) && StrUtils.isEmpty(projectId)) {
            return ok(CodeEnum.REQUEST_PARAM_NOT_FULL_ERROR);
        }
        return ok(getDifferenceReview(projectId, businessKey));
    }

    /**
     * 导出货值审批-全盘货值差异概览
     */
    @Override
    public void newAllgoodsValueReviewExport(String apiVersion, String projectId, String businessKey, HttpServletResponse response) {

        //项目信息
        BasicInfoVO basicInfoVO = prepareBaseInfo(businessKey, projectId);

        PriceApprovalDifferencesVo priceApprovalDifferencesVsAdjust = priceApprovalDifferencesService.getByBusinessKey(businessKey, CollectTypeEnum.ADJUST_BEFORE.getValue());
        PriceApprovalDifferencesVo priceApprovalDifferencesVsPricing = priceApprovalDifferencesService.getByBusinessKey(businessKey, CollectTypeEnum.GETPRICE.getValue());
        PriceApprovalDifferencesVo priceApprovalDifferencesVsStrategy = priceApprovalDifferencesService.getByBusinessKey(businessKey, CollectTypeEnum.WARPLAN.getValue());
        PriceApprovalDifferencesVo priceApprovalDifferencesVsInvestment = priceApprovalDifferencesService.getByBusinessKey(businessKey, CollectTypeEnum.CASTDECISION.getValue());

        String name = basicInfoVO.getProjectName() + "-" + "全盘货值差异" + "-" + LocalDateTimeUtils.formatTime(LocalDateTime.now(), "yyyyMMddHH");

        NewAllGoodsValueReviewTemplate newAllGoodsValueReviewTemplate = new NewAllGoodsValueReviewTemplate(name);

        newAllGoodsValueReviewTemplate.appendRows(priceApprovalDifferencesVsAdjust, 0);
        newAllGoodsValueReviewTemplate.appendRows(priceApprovalDifferencesVsPricing, 1);
        newAllGoodsValueReviewTemplate.appendRows(priceApprovalDifferencesVsStrategy, 2);
        newAllGoodsValueReviewTemplate.appendRows(priceApprovalDifferencesVsInvestment, 3);


        try (OutputStream outputStream = response.getOutputStream()) {
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name.concat(".xlsx"), "utf-8"));
            newAllGoodsValueReviewTemplate.write(outputStream);
            outputStream.flush();
        } catch (IOException e) {
            log.error("###### errorMsg: ", e);
        }

    }

    /**
     * 导出货值审批核心指标表
     */
    @Override
    public void priceApprovalCoreWarnExport(String apiVersion, String businessKey, HttpServletResponse response) {
        //项目信息
        BasicInfoVO basicInfoVO = prepareBaseInfo(businessKey, null);
        String name = basicInfoVO.getProjectName() + "-" + "本次调价对整盘核心指标的影响" + "-" + LocalDateTimeUtils.formatTime(LocalDateTime.now(), "yyyyMMddHH");

        List<PriceApprovalCoreWarn> coreWarns = priceApprovalCoreWarnService.selectByBusinessKey(businessKey);


        PriceApprovalCoreWarnTemplate template = new PriceApprovalCoreWarnTemplate();
        template.appendRows(coreWarns, 0);

        try (OutputStream outputStream = response.getOutputStream()) {
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name.concat(".xlsx"), "utf-8"));
            template.write(outputStream);
            outputStream.flush();
        } catch (IOException e) {
            log.error("###### errorMsg: ", e);
        }
    }

    /**
     * 导出本次调价楼栋
     */
    @Override
    public void priceApprovalDifferencesBuildExport(String apiVersion, String businessKey, HttpServletResponse response) {

        List<PriceApprovalDifferencesBuild> differencesBuildList = priceApprovalDifferencesBuildService.selectByBusinessKey(businessKey);
        BasicInfoVO basicInfoVO = prepareBaseInfo(businessKey, null);
        String name = basicInfoVO.getProjectName() + "-" + "本次调价楼栋" + "-" + LocalDateTimeUtils.formatTime(LocalDateTime.now(), "yyyyMMddHH");

        PriceApprovalDifferencesBuildTemplate template = new PriceApprovalDifferencesBuildTemplate();

        template.appendRows(differencesBuildList, 0);

        try (OutputStream outputStream = response.getOutputStream()) {
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name.concat(".xlsx"), "utf-8"));
            template.write(outputStream);
            outputStream.flush();
        } catch (IOException e) {
            log.error("###### errorMsg: ", e);
        }

    }

    /**
     * 货值审批-全盘货值差异概览（APP）
     */
    @Override
    public R<List<DifferenceReviewVersionVO>> appNewAllgoodsValueReview(String apiVersion, String projectId, String businessKey) {
        if (StrUtils.isEmpty(businessKey) && StrUtils.isEmpty(projectId)) {
            return ok(CodeEnum.REQUEST_PARAM_NOT_FULL_ERROR);
        }
        return ok(getDifferenceReview(projectId, businessKey));
    }

    /**
     * 货值审批-差异详情
     */

    @Override
    public R newAllgoodsValueDetail(String apiVersion, String projectId, String businessKey, String type) {
        if (StringUtils.isNotBlank(businessKey)) {
            ApprovalBill approvalBill = submitApprovedProjectService.selectApprovalBillByKey(businessKey);
            projectId = approvalBill.getProjectId();
        }
        return ok(submitApprovedProjectService.differenceDetailResultData(projectId, businessKey, type));
    }

    /**
     * 导出货值审批-差异详情
     */

    @Override
    public void newAllgoodsValueDetailExport(String apiVersion, String projectId, String businessKey, HttpServletResponse response) {

        //项目信息
        BasicInfoVO basicInfoVO = prepareBaseInfo(businessKey, projectId);

        String name = basicInfoVO.getProjectName() + "-" + "全盘货值差异详情" + "-" + LocalDateTimeUtils.formatTime(LocalDateTime.now(), "yyyyMMddHH");

        NewAllgoodsValueDetailTemplate newAllgoodsValueDetailTemplate = new NewAllgoodsValueDetailTemplate(name);

        List<PriceApprovalDifferencesDetail> adjustBefore = priceApprovalDifferencesDetailService.selectByBillIdAndType(businessKey, CollectTypeEnum.ADJUST_BEFORE.getValue());
        List<PriceApprovalDifferencesDetail> pricing = priceApprovalDifferencesDetailService.selectByBillIdAndType(businessKey, CollectTypeEnum.GETPRICE.getValue());
        List<PriceApprovalDifferencesDetail> strategy = priceApprovalDifferencesDetailService.selectByBillIdAndType(businessKey, CollectTypeEnum.WARPLAN.getValue());
        List<PriceApprovalDifferencesDetail> investment = priceApprovalDifferencesDetailService.selectByBillIdAndType(businessKey, CollectTypeEnum.CASTDECISION.getValue());

        newAllgoodsValueDetailTemplate.appendRows(adjustBefore, 0, basicInfoVO.getProjectCode());
        newAllgoodsValueDetailTemplate.appendRows(pricing, 1, basicInfoVO.getProjectCode());
        newAllgoodsValueDetailTemplate.appendRows(strategy, 2, basicInfoVO.getProjectCode());
        newAllgoodsValueDetailTemplate.appendRows(investment, 3, basicInfoVO.getProjectCode());

        try (OutputStream outputStream = response.getOutputStream()) {
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name.concat(".xlsx"), "utf-8"));
            newAllgoodsValueDetailTemplate.write(outputStream);
            outputStream.flush();
        } catch (IOException e) {
            log.error("###### errorMsg: ", e);
        }

    }

    /**
     * APP货值审批-差异详情
     */

    @Override
    public R appAllgoodsValueDetail(String apiVersion, String projectId, String businessKey, String type) {
        if (StringUtils.isNotBlank(businessKey)) {
            ApprovalBill approvalBill = submitApprovedProjectService.selectApprovalBillByKey(businessKey);
            projectId = approvalBill.getProjectId();
        }
        return ok(submitApprovedProjectService.differenceDetailResultData(projectId, businessKey, type));
    }

    public DifferenceReviewVO newCalDifference(ValueReviewVersionContentVO adjustAfterVO, ValueReviewVersionContentVO vo) {
        DifferenceReviewVO diffVo = new DifferenceReviewVO();
        if (adjustAfterVO == null) {
            adjustAfterVO = new ValueReviewVersionContentVO();
        }
        if (vo == null) {
            vo = new ValueReviewVersionContentVO();
        }
        //总货值
        BigDecimal totalValueDiff = adjustAfterVO.getTotalValue().subtract(vo.getTotalValue());
        BigDecimal totalValuePer = parpareDiffPer(vo.getTotalValue(), adjustAfterVO.getTotalValue());
        diffVo.setTotalValueDiff(totalValueDiff);
        diffVo.setTotalValuePer(totalValuePer);
        //权益货值
        BigDecimal quityValueDiff = adjustAfterVO.getQuityValue().subtract(vo.getQuityValue());
        BigDecimal quityValuePer = parpareDiffPer(vo.getQuityValue(), adjustAfterVO.getQuityValue());
        diffVo.setQuityValueDiff(quityValueDiff);
        diffVo.setQuityValuePer(quityValuePer);
        //房源货值
        BigDecimal houseCommodityValueCountDiff = adjustAfterVO.getHouseCommodityValueCount().subtract(vo.getHouseCommodityValueCount());
        BigDecimal houseCommodityValueCountPer = parpareDiffPer(vo.getHouseCommodityValueCount(), adjustAfterVO.getHouseCommodityValueCount());
        diffVo.setHouseCommodityValueCountDiff(houseCommodityValueCountDiff);
        diffVo.setHouseCommodityValueCountPer(houseCommodityValueCountPer);
        //房源均价
        BigDecimal houseAvgDiff = adjustAfterVO.getHouseAvg().subtract(vo.getHouseAvg());
        BigDecimal houseAvgPer = parpareDiffPer(vo.getHouseAvg(), adjustAfterVO.getHouseAvg());
        diffVo.setHouseAvgDiff(houseAvgDiff);
        diffVo.setHouseAvgPer(houseAvgPer);
        //房源面积
        BigDecimal saleAreaCountDiff = adjustAfterVO.getSaleAreaCount().subtract(vo.getSaleAreaCount());
        BigDecimal saleAreaCountPer = parpareDiffPer(vo.getSaleAreaCount(), adjustAfterVO.getSaleAreaCount());
        diffVo.setSaleAreaCountDiff(saleAreaCountDiff);
        diffVo.setSaleAreaCountPer(saleAreaCountPer);
        //总房源
        int roomNumCountDiff = adjustAfterVO.getRoomNumCount() - vo.getRoomNumCount();
        BigDecimal roomNumCountPer = parpareDiffPer(new BigDecimal(vo.getRoomNumCount()), new BigDecimal(adjustAfterVO.getRoomNumCount()));
        diffVo.setRoomNumCountDiff(roomNumCountDiff);
        diffVo.setRoomNumCountPer(roomNumCountPer);
        //可售车位货值
        BigDecimal parkingValueCountDiff = adjustAfterVO.getParkingValueCount().subtract(vo.getParkingValueCount());
        BigDecimal parkingValueCountPer = parpareDiffPer(vo.getParkingValueCount(), adjustAfterVO.getParkingValueCount());
        diffVo.setParkingValueCountDiff(parkingValueCountDiff);
        diffVo.setParkingValueCountPer(parkingValueCountPer);
        //可售车位均价
        BigDecimal parkingAvgDiff = adjustAfterVO.getParkingAvg().subtract(vo.getParkingAvg());
        BigDecimal parkingAvgPer = parpareDiffPer(vo.getParkingAvg(), adjustAfterVO.getParkingAvg());
        diffVo.setParkingAvgDiff(parkingAvgDiff);
        diffVo.setParkingAvgPer(parkingAvgPer);
        //可售车位数
        int parkingNumCountDiff = adjustAfterVO.getParkingNumCount() - vo.getParkingNumCount();
        BigDecimal parkingNumCountPer = parpareDiffPer(new BigDecimal(vo.getParkingNumCount()), new BigDecimal(adjustAfterVO.getParkingNumCount()));
        diffVo.setParkingNumCountDiff(parkingNumCountDiff);
        diffVo.setParkingNumCountPer(parkingNumCountPer);
        //未推售车位货值
        BigDecimal forSaleParkingValueCountDiff = adjustAfterVO.getForSaleParkingValueCount().subtract(vo.getForSaleParkingValueCount());
        BigDecimal forSaleParkingValueCountPer = parpareDiffPer(vo.getForSaleParkingValueCount(), adjustAfterVO.getForSaleParkingValueCount());
        diffVo.setForSaleParkingValueCountDiff(forSaleParkingValueCountDiff);
        diffVo.setForSaleParkingValueCountPer(forSaleParkingValueCountPer);
        //未推售车位数
        int forSaleParkingNumCountDiff = adjustAfterVO.getForSaleParkingNumCount() - vo.getForSaleParkingNumCount();
        BigDecimal forSaleparkingNumCountPer = parpareDiffPer(new BigDecimal(vo.getForSaleParkingNumCount()), new BigDecimal(adjustAfterVO.getForSaleParkingNumCount()));
        diffVo.setForSaleParkingNumCountDiff(forSaleParkingNumCountDiff);
        diffVo.setForSaleParkingNumCountPer(forSaleparkingNumCountPer);
        return diffVo;
    }

    private BigDecimal parpareDiffPer(BigDecimal compareValue, BigDecimal afterValue) {
        if (compareValue.compareTo(BigDecimal.ZERO) != 0 && afterValue.compareTo(BigDecimal.ZERO) != 0) {
            BigDecimal totalValueDiff = afterValue.subtract(compareValue);
            return totalValueDiff.divide(compareValue, 4, BigDecimal.ROUND_HALF_UP);
        } else if (compareValue.compareTo(BigDecimal.ZERO) == 0 && afterValue.compareTo(BigDecimal.ZERO) != 0) {
            BigDecimal totalValueDiff = afterValue.subtract(compareValue);
            return totalValueDiff.divide(afterValue, 4, BigDecimal.ROUND_HALF_UP);
        } else if (compareValue.compareTo(BigDecimal.ZERO) != 0 && afterValue.compareTo(BigDecimal.ZERO) == 0) {
            BigDecimal totalValueDiff = afterValue.subtract(compareValue);
            return totalValueDiff.divide(compareValue, 4, BigDecimal.ROUND_HALF_UP);
        } else {
            return BigDecimal.ZERO;
        }
    }

    /**
     * 货值审批-提交到OA审批操作
     */
    @Override
    public R<Map<String, String>> submitToOA(String apiVersion, PriceApproveReqParam priceApproveReqParam) {
        String projectId = priceApproveReqParam.getProjectId();
        String businessType = priceApproveReqParam.getBusinessType();
        String businessKey = priceApproveReqParam.getBusinessKey();
        String description = priceApproveReqParam.getDescription();
        int batchAdjust = 0;
        List<String> files = priceApproveReqParam.getFiles();
        //查询是否有审批中的版本
        List<PriceVersion> priceVersionList = submitApprovedProjectService.checkSubmitToOA(projectId);
        if (CollectionUtils.isNotEmpty(priceVersionList)) {
            throw new MsgException(CodeEnum.APPROVED_EXISTENT);
        }
        List<PriceVersion> versionList = submitApprovedProjectService.selectApprovedProject(projectId);
        if (CollectionUtils.isNotEmpty(versionList)) {
            batchAdjust = versionList.get(0).getBatchAdjust();
        }

        ApprovalBill resApprovalBill = null;
        if (StringUtils.isNotBlank(businessKey)) {
            resApprovalBill = submitApprovedProjectService.selectApprovalBillByKey(businessKey);
            projectId = resApprovalBill.getProjectId();
        }

        IdmUser user = getOperator();
        String account = user.getAlias();
        String name = user.getUsercn();
        String orgCode = user.getDepartmentnumber();
        String postCode = user.getPositionid();
        Map<String, String> map = new HashMap<>();

        String flowKey = submitApprovedProjectService.getFlowKey(businessType, projectId);

        if (StringUtils.isEmpty(flowKey)) {
            throw new MsgException(CodeEnum.FLOW_KEY_IS_NULL);
        }

        saveLog("货值审批", "提交OA审批信息", JSON.toJSONString(priceApproveReqParam));

        //查询项目名称
        String projectName = "";
        MdmProject mdmProject = projectService.selectByProId(projectId);
        if (mdmProject != null) {
            projectName = mdmProject.getProjectName();
        }
        int warnFlag = WhetherEnum.NO.getKey();
        int isPresident = WhetherEnum.NO.getKey();
        int confirmFlag = WhetherEnum.NO.getKey();
        PriceApproveWarnInfoVO approveWarnInfoVO = priceApproveReqParam.getApproveWarnInfoVO();
        if (approveWarnInfoVO != null) {
            List<BulletinWarnInfoVO> bulletinWarnInfo = approveWarnInfoVO.getBulletinWarnInfo();
            if (CollectionUtils.isNotEmpty(bulletinWarnInfo)) {
                //货值变动-一级指标
                String priceStatus = getStatus(1, bulletinWarnInfo);
                //创造利润率-一级指标
                String rateStatus = getStatus(2, bulletinWarnInfo);

                //楼栋均价-二级指标
                String buildAvg = getStatus(0, bulletinWarnInfo);
                //非融IRR-二级指标
                String meltingIRR = getStatus(3, bulletinWarnInfo);
                //非融静态投资回收期-二级指标
                String meltingInvestment = getStatus(4, bulletinWarnInfo);

                //一级指标任一触发预警，发起审批时，需要发送预警待办给非集团高管人员，审批通过后，不发送预警待办给集团高管人员，不发送督办确认待办;
                if (priceStatus.equals("warning") || rateStatus.equals("warning")) {
                    isPresident = WhetherEnum.YES.getKey();
                    warnFlag = WhetherEnum.YES.getKey();
                } else {//一级指标都不触发预警，二级指标任一触发预警，发起审批时，需要发送预警待办给非集团高管人员，审批通过后，发送预警待办给集团高管人员，同时发送督办确认待办
                    if (buildAvg.equals("warning") || meltingIRR.equals("warning") || meltingInvestment.equals("warning")) {
                        warnFlag = WhetherEnum.YES.getKey();
                        confirmFlag = WhetherEnum.YES.getKey();
                    }
                }
            }
            approveWarnInfoVO.setWarnFlag(warnFlag);
            approveWarnInfoVO.setIsPresident(isPresident);
            approveWarnInfoVO.setConfirmFlag(confirmFlag);
        }

        //审批标题
        String subject = "【货值审批】" + projectName + "货值审批";
        if (StringUtils.isNotBlank(projectId) || StringUtils.isNotBlank(businessKey)) {
            if (resApprovalBill == null) {
                resApprovalBill = submitApprovedProjectService.saveBusinessData(projectId, businessType, flowKey, account, postCode, orgCode, description, subject, name);
            }
            if (resApprovalBill != null && StrUtils.isNotEmpty(resApprovalBill.getState())) {
                if (resApprovalBill.getState().equals(ApprovedStateCodeEnum.APPROVAL.getKey())
                        || resApprovalBill.getState().equals(ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey())
                        || resApprovalBill.getState().equals(ApprovedStateCodeEnum.ENDFLOW.getKey())
                        || resApprovalBill.getState().equals(ApprovedStateCodeEnum.DELETE.getKey())) {
                    throw new MsgException(CodeEnum.LOCKBILL_CANNOT_SUBMIT);
                }
            }
            List<DifferenceReviewVersionVO> list = getDifferenceReview(projectId, "");
            String resInstId = resApprovalBill.getInstanceId();
            businessKey = resApprovalBill.getId();
            String state = resApprovalBill.getState();
            String taskId = resApprovalBill.getTaskId();
            String key = resApprovalBill.getFlowKey();
            //更新审批说明和流程key
            if (StringUtils.isNotBlank(resInstId) || !(key.equals(flowKey))) {
                //根据businessKey更新审批说明
                submitApprovedProjectService.updateDescByBusinessKey(businessKey, description, flowKey, account, name);
            }
            JSONObject jsonObjectSave = new JSONObject();
            String authToken = approvalBillService.getAuthToken();
            //创建流程变量
            JSONObject vars = new JSONObject();
            vars.put("projectOrgCode", projectId);
            vars.put("versionTypeCode", getVersionStage(projectId));
            vars.put("valueDifference", getValueDifference(projectId, list));
            vars.put("batch_adjust", batchAdjust);
            vars.put("isPresident", isPresident);

            //设置OA保存流程实例接口的参数
            jsonObjectSave.put("account", account);
            jsonObjectSave.put("postCode", "");
            jsonObjectSave.put("orgCode", "");
            jsonObjectSave.put("businessKey", businessKey);
            jsonObjectSave.put("flowKey", flowKey);
            jsonObjectSave.put("sysCode", sysCode);
            jsonObjectSave.put("subject", subject);
            jsonObjectSave.put("backNormal", false);
            jsonObjectSave.put("agentAccount", "");
            //发起推演组织编码（流程按此编码 组织为起始，推演审批流程）,设置为当前审批项目id
            jsonObjectSave.put("startOrgCode", projectId);
            jsonObjectSave.put("vars", vars);
            //判断是新增还是更新
            if (StringUtils.isNotBlank(resInstId)) {
                jsonObjectSave.put("instanceId", resInstId);
            } else {
                jsonObjectSave.put("instanceId", "");
            }
            String requestSave = jsonObjectSave.toString();

            log.info("提交到OA：" + requestSave);

            saveLog("货值审批", "提交到OA审批操作", requestSave);

            //请求OA保存流程实例接口
            JSONObject parseObject = new JSONObject();

            String res = approvalBillService.saveFlow(authToken, requestSave);
            saveLog("货值审批", "保存流程实例", res);
            //保存审批单日志
            saveApprovalLog(businessKey, state, res);

            parseObject = JSONObject.parseObject(res);
            if (!parseObject.getBoolean("state")) {
                CodeEnum.SAVE_FLOW.setMessage(parseObject.getString("message"));
                throw new MsgException(CodeEnum.SAVE_FLOW);
            }

            String previewUrl = null;
            JSONObject instObject = new JSONObject();
            String instId = parseObject.getString("instId");

            if (StringUtils.isNotBlank(resInstId)) {
                if (state.equals(ApprovedStateCodeEnum.RECALL.getKey()) || state.equals(ApprovedStateCodeEnum.REJECT.getKey())) {
                    instObject.put("taskId", taskId);
                    submitApprovedProjectService.updateApprovalState(businessKey, state, instId, taskId, LocalDateTime.now());
                } else {
                    submitApprovedProjectService.updateApprovalState(businessKey, ApprovedStateCodeEnum.DRAFT.getKey(), instId, null, LocalDateTime.now());
                }
                instObject.put("proInstId", resInstId);
            } else {
                submitApprovedProjectService.updateApprovalState(businessKey, ApprovedStateCodeEnum.DRAFT.getKey(), instId, null, LocalDateTime.now());
                instObject.put("proInstId", instId);

                saveVersionLog2(businessKey, account, resInstId);

                //将每个被审批的版本的状态改为待提交审批
                List<ApprovalBillDetail> approvalBillDetails = approvalBillDetailService.selectApprovalBillDetail(businessKey);
                if (CollectionUtils.isNotEmpty(approvalBillDetails)) {
                    List<String> versionIds = approvalBillDetails.stream().map(ApprovalBillDetail::getVersionId).collect(toList());
                    priceVersionService.updateStateById(versionIds, VersionStatusEnum.EXAMINEDAPPROVED.getKey(), account);
                }
            }

            //保存预警信息
            approvalWarningService.save(projectId, businessKey, priceApproveReqParam.getApproveWarnInfoVO());
            if (CollectionUtils.isNotEmpty(files)) {
                fileUploadService.updateBillId(businessKey, files);
            }
            try {
                String encode = Base64.getEncoder().encodeToString(instObject.toString().getBytes("utf-8"));
                //跳转的url
                previewUrl = url + encode;
                map.put("previewUrl", previewUrl);
            } catch (UnsupportedEncodingException e) {
                log.error("###### errorMsg: ", e);
            }
        }

        //保存审批单日志
        saveApprovalLog(businessKey, ApprovedStateCodeEnum.DRAFT.getKey(), JSON.toJSONString(priceApproveReqParam));

        return ok(map);
    }

    private String getStatus(int index, List<BulletinWarnInfoVO> bulletinWarnInfo) {
        try {
            return bulletinWarnInfo.get(index).getStatus();
        } catch (Exception e) {
            return "success";
        }
    }

    private void saveVersionLog2(String instanceId, String alias, String resInstId) {
        String beforeState = "";
        String afterState = "";
        List<PriceVersion> list = submitApprovedProjectService.selectVersionByBillId(instanceId);
        if (CollectionUtils.isNotEmpty(list)) {
            for (PriceVersion version : list) {
                if (version != null) {
                    String versionName = prepareVersionName(version, "");
                    beforeState = version.getVersionState();
                    if (StringUtils.isNotBlank(resInstId)) {
                        afterState = VersionStatusEnum.FAILUREAPPROVED.getKey();
                    } else {
                        afterState = VersionStatusEnum.EXAMINEDAPPROVED.getKey();
                    }
                    versionLogService.saveVersionLogInfo(version.getProjectId(), version.getProjectfId(), ModuleTypeEunm.PRICE.getKey(),
                            VersionEventEnum.INITIATE_APPROVAL.getKey(), version.getId(), versionName, beforeState, afterState, ModifySourceTypeEunm.TWO.getKey(),
                            version.getId(), alias, LocalDateTime.now(), "货值审批", "提交到OA审批", IsDeleteEnum.NO.getKey(), alias, LocalDateTime.now());
                }
            }
        }
    }

    public String getVersionStage(String projectId) {
        Set<String> versionStageSet = new TreeSet<>();
        List<PriceVersion> priceVersionList = submitApprovedProjectService.selectApprovedProject(projectId);
        if (CollectionUtils.isNotEmpty(priceVersionList)) {
            for (PriceVersion priceVersion : priceVersionList) {
                versionStageSet.add(priceVersion.getVersionType());
            }
        }
        if (versionStageSet.contains(VersionTypeEunm.DYNAMIC.getKey())) {
            return VersionTypeEunm.DYNAMIC.getKey();
        } else if (versionStageSet.contains(VersionTypeEunm.GETPRICE.getKey())) {
            return VersionTypeEunm.GETPRICE.getKey();
        } else if (versionStageSet.contains(VersionTypeEunm.WARPLAN.getKey())) {
            return VersionTypeEunm.WARPLAN.getKey();
        } else {
            return VersionTypeEunm.INVESTMENT.getKey();
        }
    }

    public double getValueDifference(String projectId, List<DifferenceReviewVersionVO> list) {
        BigDecimal value = BigDecimal.ZERO;
        for (DifferenceReviewVersionVO vo : list) {
            String versionName = vo.getVersionName();
            if (versionName.equals("调整前")) {
                value = vo.getDifferenceVO().getTotalValueDiff();
            }
        }
        if (value.compareTo(BigDecimal.ZERO) == 0) {
            return value.doubleValue();
        } else {
            value = NumberUtils.divide(value, new BigDecimal(10000), 2);
            return value.doubleValue();
        }
    }


    private void saveApprovalLog(String businessKey, String state, String res) {
        ApprovalLog approvalLog = new ApprovalLog();
        approvalLog.setId(UUIDUtils.create());
        approvalLog.setBillId(businessKey);
        approvalLog.setState(state);
        approvalLog.setSource("mars");
        approvalLog.setContent(res);
        approvalLog.setDescription("货值审批，提交到OA审批，保存流程实例");
        approvalLog.setCreatedTime(LocalDateTime.now());
        approvalLogService.add(approvalLog);
    }

    /**
     * 查看货值审批记录
     */
    @Override
    public R<ApprovedRecordViewVO> goodsApprovedRecordView(String apiVersion, String projectId, String searchStr, String current, String pageSize, String businessType) {
        ApprovedRecordViewVO approvedRecordViewVO = null;
        IdmUser user = getOperator();
        if (StringUtils.isNotBlank(projectId)) {
            approvedRecordViewVO = approvedRecoreViewService.selectRecordById(projectId, searchStr, user, current, pageSize, businessType);
        }
        return ok(approvedRecordViewVO);
    }

    /**
     * 查看货值审批
     */
    @Override
    public R<ApprovedViewVO> goodsApprovedView(String apiVersion, String versionId) {
        ApprovedViewVO vo;
        ApprovalBill approvalBill = approvedRecoreViewService.selectBillByVersionId(versionId);
        if (null != approvalBill) {
            IdmUser user = getOperator();
            String alias = user.getAlias();
            vo = approvedRecoreViewService.getResultUrl(approvalBill, alias);
        } else {
            throw new MsgException(CodeEnum.APPROVED_FLOW_NON_EXISTENT);
        }
        return ok(vo);
    }

    /**
     * 废弃流程实例
     */
    @Override
    public R endFlow(String apiVersion, String instanceId) {
        IdmUser user = getOperator();
        String alias = user.getAlias();
        String account = null;
        String businessType = null;
        //根据instanceId查询对应的审批的发起人
        ApprovalBill approvalBill = approvedRecoreViewService.selectByInstId(instanceId);
        if (null != approvalBill) {
            account = approvalBill.getAccount();
            businessType = approvalBill.getBusinessType();
            String billId = approvalBill.getId();
            if (alias.equalsIgnoreCase(account)) {
                String authToken = approvalBillService.getAuthToken();
                JSONObject jsonEnd = new JSONObject();
                jsonEnd.put("instanceId", instanceId);
                jsonEnd.put("sysCode", sysCode);
                String responseStr = approvalBillService.endFlow(authToken, jsonEnd.toString());
                JSONObject jsonParse = JSONObject.parseObject(responseStr);
                Boolean state = jsonParse.getBoolean("state");
                String message = jsonParse.getString("message");
                if (state) {
                    List<ApprovalBillDetail> approvalBillDetails = approvalBillDetailService.selectApprovalBillDetail(billId);
                    submitApprovedProjectService.updateApprovalState(billId, ApprovedStateCodeEnum.ENDFLOW.getKey(), instanceId, null, LocalDateTime.now());
                    if (CollectionUtils.isNotEmpty(approvalBillDetails)) {
                        if (businessType.equals(ProcessTypeEnum.PRICE_MANAGEMENT.getKey())) {
                            //记录版本日志
                            saveVersionLog(billId, alias, ProcessTypeEnum.PRICE_MANAGEMENT.getKey());
                            //修改货值审批状态
                            List<String> versionIds = approvalBillDetails.stream().map(ApprovalBillDetail::getVersionId).collect(toList());
                            priceVersionService.updateStateById(versionIds, VersionStatusEnum.ORGANIZATION.getKey(), account);

                            approvalPreviewService.cleanPriceWarnTodo(billId, user);
                        } else if (businessType.equals(ProcessTypeEnum.SIGNING_PLAN.getKey())) {
                            //修改签约计划审批状态
                            for (ApprovalBillDetail approvalBillDetail : approvalBillDetails) {
                                String versionId = approvalBillDetail.getVersionId();
                                SignPlanVersion version = signPlanVersionMapper.selectById(versionId);
                                String versionName = VersionUtils.getFullName(version);

                                //修改签约计划版本状态
                                signPlanVersionMapper.updateSignPlanVersionState(VersionStatusEnum.ORGANIZATION.getKey(), versionId, LocalDateTime.now());
                                //记录版本日志
                                versionLogService.saveVersionLogInfo(version.getProjectId(), version.getProjectfId(), ModuleTypeEunm.PRICE.getKey(),
                                        VersionEventEnum.TO_VOID_APPROVAL.getKey(), version.getId(), versionName, version.getVersionState(), VersionStatusEnum.ORGANIZATION.getKey(), null,
                                        version.getId(), alias, LocalDateTime.now(), "签约审批", "废弃签约审批单", IsDeleteEnum.NO.getKey(), alias, LocalDateTime.now());

                            }
                            //对签约审批单查看内容缓存处理
                            signPlanVersionService.handApprovalBillBuffer(instanceId, ApprovedStateCodeEnum.ENDFLOW.getKey());
                        } else if (businessType.equals(ProcessTypeEnum.MONEY_BACK_COEFFICIENT.getKey())) {
                            ApprovalPreview approvalPreview = approvalPreviewMapper.selectByBillId(billId, IsDeleteEnum.NO.getKey());
                            if (null == approvalPreview) {
                                throw new MsgException(CodeEnum.SYS_OPER_ERROR);
                            }
                            String contentString = approvalPreview.getContent();
                            ReturnCoefficientContent content = JsonUtils.convertJsonToBean(contentString, ReturnCoefficientContent.class);
                            if (null == content) {
                                throw new MsgException(CodeEnum.SYS_OPER_ERROR);
                            }

                            String coefficientId = content.getCoefficientId();

                            //修改回款系数审批状态为编制中
                            returnCoefficientMapper.updateCoefficientType(coefficientId, VersionStatusEnum.ORGANIZATION.getKey(), LocalDateTime.now());


                        } else if (businessType.equals(ProcessTypeEnum.MONEY_BACK_PLAN.getKey())) {
                            List<String> versionIds = approvalBillDetails.stream().map(ApprovalBillDetail::getVersionId).collect(toList());
                            returnPlanVersionService.updateState(versionIds, VersionEventEnum.TO_VOID_APPROVAL.getKey(), VersionStatusEnum.ORGANIZATION.getKey(), user);
                        }
                    }
                    //保存审批单日志
                    saveApprovalLog(billId, ApprovedStateCodeEnum.ENDFLOW.getKey(), responseStr);
                } else {
                    CodeEnum.FLOW_NOT_END.setMessage(message);
                    throw new MsgException(CodeEnum.FLOW_NOT_END);
                }
            } else {
                throw new MsgException(CodeEnum.PERMISSION_DENIED);
            }
        } else {
            throw new MsgException(CodeEnum.FLOW_NOT_EXIST);
        }

        return ok();
    }

    /**
     * 删除流程实例
     */
    @Override
    public R<OperateVO> deleteFlow(String apiVersion, String instanceId) {
        OperateVO vo = new OperateVO();
        IdmUser user = getOperator();
        String alias = user.getAlias();
        String account = null;
        //根据instanceId查询对应的审批的发起人
        ApprovalBill approvalBill = approvedRecoreViewService.selectByInstId(instanceId);
        if (null != approvalBill) {
            account = approvalBill.getAccount();
            if (alias.equalsIgnoreCase(account)) {
                String authToken = approvalBillService.getAuthToken();
                JSONObject jsonEnd = new JSONObject();
                jsonEnd.put("instanceId", instanceId);
                jsonEnd.put("sysCode", sysCode);
                String s = jsonEnd.toString();
                String responseStr = approvalBillService.deleteFlow(authToken, s);
                saveLog("OA删除流程", "删除流程实例", responseStr);
                JSONObject jsonParse = JSONObject.parseObject(responseStr);
                Boolean state = jsonParse.getBoolean("state");
                String message = jsonParse.getString("message");
                if (state) {
                    vo.setMessage(message);
                } else {
                    String msg = CodeEnum.DELETE_FLOW_FAIL.getMessage() + message;
                    CodeEnum.DELETE_FLOW_FAIL.setMessage(msg);
                    throw new MsgException(CodeEnum.DELETE_FLOW_FAIL);
                }
            } else {
                throw new MsgException(CodeEnum.PERMISSION_DENIED);
            }
        } else {
            throw new MsgException(CodeEnum.FLOW_NOT_EXIST);
        }
        return ok(vo);
    }

    private void saveVersionLog(String billId, String alias, String processType) {
        if (processType.equals(ProcessTypeEnum.PRICE_MANAGEMENT.getKey())) {
            String beforeState = "";
            String afterState = "";
            List<PriceVersion> list = submitApprovedProjectService.selectVersionByBillId(billId);
            if (CollectionUtils.isNotEmpty(list)) {
                for (PriceVersion version : list) {
                    if (version != null) {
                        String versionName = prepareVersionName(version, "");
                        beforeState = version.getVersionState();
                        afterState = VersionStatusEnum.ORGANIZATION.getKey();
                        versionLogService.saveVersionLogInfo(version.getProjectId(), version.getProjectfId(), ModuleTypeEunm.PRICE.getKey(),
                                VersionEventEnum.TO_VOID_APPROVAL.getKey(), version.getId(), versionName, beforeState, afterState, ModifySourceTypeEunm.TWO.getKey(),
                                version.getId(), alias, LocalDateTime.now(), "货值审批", "废弃货值审批单", IsDeleteEnum.NO.getKey(), alias, LocalDateTime.now());
                    }
                }
            }
        }
    }

    //#################货值审批差异概览 重构 -2020-04-20######################################################
    private ValueReviewVersionContentVO prepareCompareValue(String collectType, List<ApprovalVersionCompare> approvalVersionCompares, MdmProjectPatner projectPatner) {
        //详情对象（用于封装数据）
        ValueReviewVersionContentVO content = new ValueReviewVersionContentVO();
        //计算返回的数值
        //总房源数
        int roomNumCount = 0;
        //可售车位数
        int parkingNumCount = 0;
        //未推售车位数
        int forSaleParkingNumCount = 0;
        //房源货值
        BigDecimal houseCommodityValueCount = BigDecimal.ZERO;
        //可售车位货值
        BigDecimal parkingValueCount = BigDecimal.ZERO;
        //未推售车位货值
        BigDecimal forSaleParkingValueCount = BigDecimal.ZERO;
        //总面积
        BigDecimal saleAreaCount = BigDecimal.ZERO;
        //总货值
        BigDecimal totalValue = BigDecimal.ZERO;
        //权益货值
        BigDecimal quityValue = BigDecimal.ZERO;
        //房源均价
        BigDecimal houseAvg = BigDecimal.ZERO;
        //车位均价
        BigDecimal parkingAvg = BigDecimal.ZERO;

        List<String> versionCompares = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(approvalVersionCompares)) {
            for (ApprovalVersionCompare obj : approvalVersionCompares) {
                String stageStatus = obj.getStageStatus();
                if (obj.getCollectType().equals(collectType)) {
                    if (collectType.equals(CollectTypeEnum.ADJUST_AFTER.getKey()) || collectType.equals(CollectTypeEnum.ADJUST_BEFORE.getKey())) {
                        if (StringUtils.isEmpty(stageStatus) || stageStatus.equals(StageStatusEnum.CTIVE.getKey())) {
                            if (obj.getCollectType().equals(collectType)) {
                                versionCompares.add(obj.getVersionIdCompare());
                            }
                        }
                    } else {
                        if (obj.getCollectType().equals(collectType)) {
                            versionCompares.add(obj.getVersionIdCompare());
                        }
                    }
                }
            }
        }

        if (CollectionUtils.isNotEmpty(versionCompares)) {
            for (String versionId : versionCompares) {
                PriceValueOrg priceValueOrg = priceVersionService.selectViewDataById(versionId);
                if (priceValueOrg != null) {
                    PriceVersion version = priceVersionService.selectById(versionId);
                    String valueString = priceVersionService.selectArea(versionId, version.getVersionType());

                    Integer roomNum = priceValueOrg.getRoomNum() == null ? 0 : priceValueOrg.getRoomNum();
                    roomNumCount = roomNumCount + roomNum;

                    Integer parkingNum = priceValueOrg.getParkingNum() == null ? 0 : priceValueOrg.getParkingNum();
                    parkingNumCount = parkingNumCount + parkingNum;

                    Integer forsaleParkingNum = priceValueOrg.getForsaleParkingNum() == null ? 0 : priceValueOrg.getForsaleParkingNum();
                    forSaleParkingNumCount = forSaleParkingNumCount + forsaleParkingNum;

                    BigDecimal houseCommodityValue = priceValueOrg.getHouseCommodityValue() == null ? BigDecimal.ZERO : priceValueOrg.getHouseCommodityValue();
                    houseCommodityValueCount = houseCommodityValueCount.add(houseCommodityValue);

                    BigDecimal notCommodityValue = priceValueOrg.getNotCommodityValue() == null ? BigDecimal.ZERO : priceValueOrg.getNotCommodityValue();
                    parkingValueCount = parkingValueCount.add(notCommodityValue);

                    BigDecimal commodityValue = priceValueOrg.getCommodityValue() == null ? BigDecimal.ZERO : priceValueOrg.getCommodityValue();
                    forSaleParkingValueCount = forSaleParkingValueCount.add(commodityValue);

                    BigDecimal saleArea = StrUtils.isEmpty(valueString) ? BigDecimal.ZERO : new BigDecimal(valueString);
                    saleAreaCount = saleAreaCount.add(saleArea);
                }
            }
            totalValue = houseCommodityValueCount.add(parkingValueCount);
            //查询权益比例
            if (null != projectPatner.getEquityRatio()) {
                //计算权益货值
                BigDecimal divide = projectPatner.getEquityRatio().divide(new BigDecimal("100"), 4, BigDecimal.ROUND_HALF_UP);
                quityValue = totalValue.multiply(divide);
            }
            if (null != saleAreaCount && saleAreaCount.compareTo(BigDecimal.ZERO) != 0) {
                houseAvg = houseCommodityValueCount.divide(saleAreaCount, 4, BigDecimal.ROUND_HALF_UP);
            }
            BigDecimal parkingNumCountDec = new BigDecimal(parkingNumCount);
            if (null != parkingNumCountDec && parkingNumCountDec.compareTo(BigDecimal.ZERO) != 0) {
                parkingAvg = parkingValueCount.divide(parkingNumCountDec, 4, BigDecimal.ROUND_HALF_UP);
            }
        } else if (collectType.equals(CollectTypeEnum.ADJUST_BEFORE.getKey()) && CollectionUtils.isEmpty(versionCompares)) {
            content.setRoomNumCount(roomNumCount);
            content.setParkingNumCount(parkingNumCount);
            content.setForSaleParkingNumCount(forSaleParkingNumCount);
            content.setHouseCommodityValueCount(houseCommodityValueCount);
            content.setParkingValueCount(parkingValueCount);
            content.setForSaleParkingValueCount(forSaleParkingValueCount);
            content.setSaleAreaCount(saleAreaCount);
            content.setTotalValue(totalValue);
            content.setQuityValue(quityValue);
            content.setHouseAvg(houseAvg);
            content.setParkingAvg(parkingAvg);
            return content;
        } else {
            return null;
        }
        content.setRoomNumCount(roomNumCount);
        content.setParkingNumCount(parkingNumCount);
        content.setForSaleParkingNumCount(forSaleParkingNumCount);
        content.setHouseCommodityValueCount(houseCommodityValueCount);
        content.setParkingValueCount(parkingValueCount);
        content.setForSaleParkingValueCount(forSaleParkingValueCount);
        content.setSaleAreaCount(saleAreaCount);
        content.setTotalValue(totalValue);
        content.setQuityValue(quityValue);
        content.setHouseAvg(houseAvg);
        content.setParkingAvg(parkingAvg);
        return content;
    }

    private List<DifferenceReviewVersionVO> getDifferenceReview(String projectId, String businessKey) {
        List<DifferenceReviewVersionVO> resultList = new ArrayList<>();
        if (StringUtils.isNotBlank(businessKey)) {
            ApprovalBill approvalBill = submitApprovedProjectService.selectApprovalBillByKey(businessKey);
            if (approvalBill != null) {
                projectId = approvalBill.getProjectId();
                if (approvalBill.getState().equals(ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey()) ||
                        approvalBill.getState().equals(ApprovedStateCodeEnum.APPROVAL.getKey())) {
                    List<ApprovalVersionCompare> approvalVersionCompares = approvalVersionCompareService.selectByBillId(businessKey);

                    //查询权益比例
                    MdmProjectPatner projectPatner = projectBasicService.selecteQuityRatio(projectId);
                    ValueReviewVersionContentVO castMaps = prepareCompareValue(CollectTypeEnum.CASTDECISION.getKey(), approvalVersionCompares, projectPatner);
                    ValueReviewVersionContentVO warPlanMaps = prepareCompareValue(CollectTypeEnum.WARPLAN.getKey(), approvalVersionCompares, projectPatner);
                    ValueReviewVersionContentVO getPriceMaps = prepareCompareValue(CollectTypeEnum.GETPRICE.getKey(), approvalVersionCompares, projectPatner);
                    ValueReviewVersionContentVO adjustAfterMaps = prepareCompareValue(CollectTypeEnum.ADJUST_AFTER.getKey(), approvalVersionCompares, projectPatner);
                    ValueReviewVersionContentVO adjustBeforeMaps = prepareCompareValue(CollectTypeEnum.ADJUST_BEFORE.getKey(), approvalVersionCompares, projectPatner);

                    //调整后 VS 投资版对比
                    if (null != castMaps) {
                        DifferenceReviewVO differenceReviewVO = newCalDifference(adjustAfterMaps, castMaps);
                        DifferenceReviewVersionVO reviewVersionVO = new DifferenceReviewVersionVO();
                        reviewVersionVO.setVersionName(CollectTypeEnum.CASTDECISION.getValue());
                        reviewVersionVO.setAfterContentVO(adjustAfterMaps);
                        reviewVersionVO.setContentVO(castMaps);
                        reviewVersionVO.setDifferenceVO(differenceReviewVO);
                        resultList.add(reviewVersionVO);
                    }
                    //调整后  VS 战规版对比
                    if (null != warPlanMaps) {
                        DifferenceReviewVO differenceReviewVO = newCalDifference(adjustAfterMaps, warPlanMaps);
                        DifferenceReviewVersionVO reviewVersionVO = new DifferenceReviewVersionVO();
                        reviewVersionVO.setVersionName(CollectTypeEnum.WARPLAN.getValue());
                        reviewVersionVO.setAfterContentVO(adjustAfterMaps);
                        reviewVersionVO.setContentVO(warPlanMaps);
                        reviewVersionVO.setDifferenceVO(differenceReviewVO);
                        resultList.add(reviewVersionVO);
                    }
                    //调整后  VS 大定价版对比
                    if (null != getPriceMaps) {
                        DifferenceReviewVO differenceReviewVO = newCalDifference(adjustAfterMaps, getPriceMaps);
                        DifferenceReviewVersionVO reviewVersionVO = new DifferenceReviewVersionVO();
                        reviewVersionVO.setVersionName(CollectTypeEnum.GETPRICE.getValue());
                        reviewVersionVO.setAfterContentVO(adjustAfterMaps);
                        reviewVersionVO.setContentVO(getPriceMaps);
                        reviewVersionVO.setDifferenceVO(differenceReviewVO);
                        resultList.add(reviewVersionVO);
                    }
                    //调整后  VS 调整前对比
                    if (null != adjustBeforeMaps) {
                        DifferenceReviewVO differenceReviewVO = newCalDifference(adjustAfterMaps, adjustBeforeMaps);
                        DifferenceReviewVersionVO reviewVersionVO = new DifferenceReviewVersionVO();
                        reviewVersionVO.setVersionName(CollectTypeEnum.ADJUST_BEFORE.getValue());
                        reviewVersionVO.setAfterContentVO(adjustAfterMaps);
                        reviewVersionVO.setContentVO(adjustBeforeMaps);
                        reviewVersionVO.setDifferenceVO(differenceReviewVO);
                        resultList.add(reviewVersionVO);
                    }
                    return resultList;
                }
            }
        }

        if (StrUtils.isNotEmpty(projectId)) {
            List<ValueReviewVersionVO> reviewVersionVOList = prepareVsData(projectId);
            DifferenceReviewVO beforeDiffVO = null;
            DifferenceReviewVO castDiffVO = null;
            DifferenceReviewVO warDiffVO = null;
            DifferenceReviewVO priceDiffVO = null;
            ValueReviewVersionContentVO afterContentVO = null;
            ValueReviewVersionContentVO beforeContentVO = null;
            ValueReviewVersionContentVO castContentVO = null;
            ValueReviewVersionContentVO warContentVO = null;
            ValueReviewVersionContentVO priceContentVO = null;
            //封装返回结果
            for (ValueReviewVersionVO versionVO : reviewVersionVOList) {
                if (versionVO.getVersionName().equals(CollectTypeEnum.ADJUST_AFTER.getValue())) {
                    afterContentVO = versionVO.getContentVO();
                }
            }
            for (ValueReviewVersionVO versionVO : reviewVersionVOList) {
                if (versionVO.getVersionName().equals(CollectTypeEnum.CASTDECISION.getValue())) {
                    DifferenceReviewVersionVO reviewVersionVO = new DifferenceReviewVersionVO();
                    castContentVO = versionVO.getContentVO();
                    castDiffVO = newCalDifference(afterContentVO, castContentVO);
                    reviewVersionVO.setVersionName(CollectTypeEnum.CASTDECISION.getValue());
                    reviewVersionVO.setAfterContentVO(afterContentVO);
                    reviewVersionVO.setContentVO(castContentVO);
                    reviewVersionVO.setDifferenceVO(castDiffVO);
                    resultList.add(reviewVersionVO);
                } else if (versionVO.getVersionName().equals(CollectTypeEnum.WARPLAN.getValue())) {
                    DifferenceReviewVersionVO reviewVersionVO = new DifferenceReviewVersionVO();
                    warContentVO = versionVO.getContentVO();
                    warDiffVO = newCalDifference(afterContentVO, warContentVO);
                    reviewVersionVO.setVersionName(CollectTypeEnum.WARPLAN.getValue());
                    reviewVersionVO.setAfterContentVO(afterContentVO);
                    reviewVersionVO.setContentVO(warContentVO);
                    reviewVersionVO.setDifferenceVO(warDiffVO);
                    resultList.add(reviewVersionVO);
                } else if (versionVO.getVersionName().equals(CollectTypeEnum.GETPRICE.getValue())) {
                    DifferenceReviewVersionVO reviewVersionVO = new DifferenceReviewVersionVO();
                    priceContentVO = versionVO.getContentVO();
                    priceDiffVO = newCalDifference(afterContentVO, priceContentVO);
                    reviewVersionVO.setVersionName(CollectTypeEnum.GETPRICE.getValue());
                    reviewVersionVO.setAfterContentVO(afterContentVO);
                    reviewVersionVO.setContentVO(priceContentVO);
                    reviewVersionVO.setDifferenceVO(priceDiffVO);
                    resultList.add(reviewVersionVO);
                } else if (versionVO.getVersionName().equals(CollectTypeEnum.ADJUST_BEFORE.getValue())) {
                    DifferenceReviewVersionVO reviewVersionVO = new DifferenceReviewVersionVO();
                    beforeContentVO = versionVO.getContentVO();
                    beforeDiffVO = newCalDifference(afterContentVO, beforeContentVO);
                    reviewVersionVO.setVersionName(CollectTypeEnum.ADJUST_BEFORE.getValue());
                    reviewVersionVO.setAfterContentVO(afterContentVO);
                    reviewVersionVO.setContentVO(beforeContentVO);
                    reviewVersionVO.setDifferenceVO(beforeDiffVO);
                    resultList.add(reviewVersionVO);
                }
            }
            return resultList;
        }

        return null;
    }

    private List<ValueReviewVersionVO> prepareVsData(String projectId) {
        List<ValueReviewVersionVO> resultList = new ArrayList<>();
        //根据projectId查询需要审批的项目的分期
        List<PriceVersion> priceVersionList = submitApprovedProjectService.selectApprovedProject(projectId);
        //根据projectId查询项目下所有分期的所有版本的个数
        List<VersionTypeCountDto> versionTypeCountDtoList = submitApprovedProjectService.selectVersionTypeCount(projectId);
        //根据projectId查询项目下所有分期个数
        List<MdmStage> approvedStageDtoList = stageService.selectByProjectId(projectId, IsDeleteEnum.NO.getKey());

        //查询权益比例
        MdmProjectPatner projectPatner = projectBasicService.selecteQuityRatio(projectId);
        //计算项目下所有分期的个数
        int stageCount = 0;
        List<String> projectfIds = new ArrayList<>();
        if (null != approvedStageDtoList) {
            stageCount = approvedStageDtoList.size();
            for (MdmStage projectByStages : approvedStageDtoList) {
                projectfIds.add(projectByStages.getProjectFid());
            }
        }
        List<String> approvedVersions = new ArrayList<String>();
        if (CollectionUtils.isNotEmpty(priceVersionList)) {
            for (PriceVersion priceVersion : priceVersionList) {
                approvedVersions.add(priceVersion.getVersionType());
            }
        }
        //遍历存有审批版本的集合 approvedVersion
        int castDecisionCount = 0;
        int strategyCount = 0;
        int getPriceCount = 0;
        int dynamicCount = 0;
        for (String versionType : approvedVersions) {
            if (VersionTypeEunm.INVESTMENT.getKey().equals(versionType)) {
                castDecisionCount++;
            } else if (VersionTypeEunm.WARPLAN.getKey().equals(versionType)) {
                strategyCount++;
            } else if (VersionTypeEunm.GETPRICE.getKey().equals(versionType)) {
                getPriceCount++;
            } else if (VersionTypeEunm.DYNAMIC.getKey().equals(versionType)) {
                dynamicCount++;
            }
        }
        //计算调整前的货值
        ValueReviewVersionVO adjustBefore = getAdjustResult(projectId, projectfIds, CollectTypeEnum.ADJUST_BEFORE.getKey());
        //计算调整后货值
        ValueReviewVersionVO adjustAfter = getAdjustResult(projectId, projectfIds, CollectTypeEnum.ADJUST_AFTER.getKey());

        resultList.add(adjustBefore);
        resultList.add(adjustAfter);
        //判断全盘货值概览需要展示的版本
        //1.全投资
        if (approvedVersions.size() == castDecisionCount) {
            int castDecisionNum = 0;
            for (VersionTypeCountDto versionTypeCountDto : versionTypeCountDtoList) {
                if (versionTypeCountDto.getVersionType().equals(VersionTypeEunm.INVESTMENT.getKey())) {
                    //审批通过或系统生成的投资版计数
                    if (isValidVersionStage(versionTypeCountDto)) {
                        castDecisionNum++;
                    }
                }
            }
            //统计的投资版个数与分期的个数是否相同
            if (castDecisionNum == stageCount) {
                ValueReviewVersionVO maps = prepareVersionData(projectId, VersionTypeEunm.INVESTMENT.getKey(), projectPatner);
                resultList.add(maps);
            }
            return resultList;
        }
        //2.全战规/（投资/战规）
        if (approvedVersions.size() == strategyCount || (castDecisionCount + strategyCount) == approvedVersions.size()) {
            int castDecisionNum = 0;
            int strategyNum = 0;
            for (VersionTypeCountDto versionTypeCountDto : versionTypeCountDtoList) {
                if (versionTypeCountDto.getVersionType().equals(VersionTypeEunm.INVESTMENT.getKey())) {
                    if (isValidVersionStage(versionTypeCountDto)) {
                        castDecisionNum++;
                    }
                }
                if (versionTypeCountDto.getVersionType().equals(VersionTypeEunm.WARPLAN.getKey())) {
                    //是否对比战规版
                    if (isValidVersionStage(versionTypeCountDto)) {
                        strategyNum++;
                    }
                }
            }

            if (castDecisionNum == stageCount) {
                ValueReviewVersionVO maps = prepareVersionData(projectId, VersionTypeEunm.INVESTMENT.getKey(), projectPatner);
                resultList.add(maps);
            }

            if (strategyNum == stageCount) {
                ValueReviewVersionVO maps = prepareVersionData(projectId, VersionTypeEunm.WARPLAN.getKey(), projectPatner);
                resultList.add(maps);
            }
            return resultList;
        }
        //3.全大定价/（投资/大定价）/（战规/大定价）/（投资/战规/大定价）
        if (approvedVersions.size() == getPriceCount || (castDecisionCount + getPriceCount) == approvedVersions.size()
                || (strategyCount + getPriceCount) == approvedVersions.size() ||
                (castDecisionCount + strategyCount + getPriceCount) == approvedVersions.size()) {
            int castDecisionNum = 0;
            int strategyNum = 0;
            int getPriceNum = 0;
            for (VersionTypeCountDto versionTypeCountDto : versionTypeCountDtoList) {
                if (versionTypeCountDto.getVersionType().equals(VersionTypeEunm.INVESTMENT.getKey())) {
                    if (isValidVersionStage(versionTypeCountDto)) {
                        castDecisionNum++;
                    }
                }
                if (versionTypeCountDto.getVersionType().equals(VersionTypeEunm.WARPLAN.getKey())) {
                    if (isValidVersionStage(versionTypeCountDto)) {
                        strategyNum++;
                    }
                }
                if (versionTypeCountDto.getVersionType().equals(VersionTypeEunm.GETPRICE.getKey())) {
                    if (isValidVersionStage(versionTypeCountDto)) {
                        getPriceNum++;
                    }
                }
            }

            if (castDecisionNum == stageCount) {
                ValueReviewVersionVO maps = prepareVersionData(projectId, VersionTypeEunm.INVESTMENT.getKey(), projectPatner);
                resultList.add(maps);
            }
            if (strategyNum == stageCount) {
                ValueReviewVersionVO maps = prepareVersionData(projectId, VersionTypeEunm.WARPLAN.getKey(), projectPatner);
                resultList.add(maps);
            }
            if (getPriceNum == stageCount) {
                ValueReviewVersionVO maps = prepareVersionData(projectId, VersionTypeEunm.GETPRICE.getKey(), projectPatner);
                resultList.add(maps);
            }
            return resultList;
        }
        //4.全动态/(投资/动态)/(战规/动态)/(大定价/动态)/(投资/战规/动态)/(投资/大定价/动态)/(战规/大定价/动态)/(投资/战规/大定价/动态)
        if (approvedVersions.size() == dynamicCount || (castDecisionCount + dynamicCount) == approvedVersions.size()
                || (strategyCount + dynamicCount) == approvedVersions.size() || (getPriceCount + dynamicCount) == approvedVersions.size()
                || (castDecisionCount + strategyCount + dynamicCount) == approvedVersions.size()
                || (castDecisionCount + getPriceCount + dynamicCount) == approvedVersions.size()
                || (strategyCount + getPriceCount + dynamicCount) == approvedVersions.size()
                || (castDecisionCount + strategyCount + getPriceCount + dynamicCount) == approvedVersions.size()
        ) {
            int castDecisionNum = 0;
            int strategyNum = 0;
            int getPriceNum = 0;
            for (VersionTypeCountDto versionTypeCountDto : versionTypeCountDtoList) {
                if (versionTypeCountDto.getVersionType().equals(VersionTypeEunm.INVESTMENT.getKey())) {
                    if (isValidVersionStage(versionTypeCountDto)) {
                        castDecisionNum++;
                    }
                }
                if (versionTypeCountDto.getVersionType().equals(VersionTypeEunm.WARPLAN.getKey())) {
                    if (isValidVersionStage(versionTypeCountDto)) {
                        strategyNum++;
                    }
                }
                if (versionTypeCountDto.getVersionType().equals(VersionTypeEunm.GETPRICE.getKey())) {
                    if (isValidVersionStage(versionTypeCountDto)) {
                        getPriceNum++;
                    }
                }
            }

            if (castDecisionNum == stageCount) {
                ValueReviewVersionVO maps = prepareVersionData(projectId, VersionTypeEunm.INVESTMENT.getKey(), projectPatner);
                resultList.add(maps);
            }
            if (strategyNum == stageCount) {
                ValueReviewVersionVO maps = prepareVersionData(projectId, VersionTypeEunm.WARPLAN.getKey(), projectPatner);
                resultList.add(maps);
            }
            if (getPriceNum == stageCount) {
                ValueReviewVersionVO maps = prepareVersionData(projectId, VersionTypeEunm.GETPRICE.getKey(), projectPatner);
                resultList.add(maps);
            }
            return resultList;
        }
        return null;
    }

    private ValueReviewVersionVO getAdjustResult(String projectId, List<String> projectfIds, String type) {
        //版本对象（封装版本和对应的数据）
        ValueReviewVersionVO versionVO = new ValueReviewVersionVO();
        //详情对象（用于封装数据）
        ValueReviewVersionContentVO content = new ValueReviewVersionContentVO();
        //计算返回的数值
        //定义总房源数
        int roomNumCount = 0;
        //定义可售车位数
        int parkingNumCount = 0;
        //定义未推售车位数
        int forSaleParkingNumCount = 0;
        //定义房源货值
        BigDecimal houseCommodityValueCount = BigDecimal.ZERO;
        //定义可售车位货值
        BigDecimal parkingValueCount = BigDecimal.ZERO;
        //定义未推售车位货值
        BigDecimal forSaleParkingValueCount = BigDecimal.ZERO;
        //定义总面积
        BigDecimal saleAreaCount = BigDecimal.ZERO;
        //总货值
        BigDecimal totalValue = BigDecimal.ZERO;
        //权益货值
        BigDecimal quityValue = BigDecimal.ZERO;
        //房源均价
        BigDecimal houseAvg = BigDecimal.ZERO;
        //可售车位均价
        BigDecimal parkingAvg = BigDecimal.ZERO;
        //未推售车位均价
        BigDecimal forSaleParkingAvg = BigDecimal.ZERO;
        //1.查询分期id
        if (CollectionUtils.isNotEmpty(projectfIds)) {
            wc:
            for (String projectfId : projectfIds) {

                //如果分期已被禁用，则不展示该分期
                if (submitApprovedProjectService.stageStateInfo(projectfId)) continue wc;

                List<Map<String, Object>> dynamicValue = submitApprovedProjectService.selectAdjustBefore(projectfId, type);
                if (CollectionUtils.isNotEmpty(dynamicValue)) {
                    for (Map<String, Object> objectMap : dynamicValue) {
                        if (String.valueOf(objectMap.get("type")).equals(OrgTypeEunm.ORG_STAGE.getKey())) {
                            String valueString = priceVersionService.selectArea(objectMap.get("versionId") + "", objectMap.get("version") + "");

                            if (null != objectMap.get("roomNum")) {
                                roomNumCount = roomNumCount + Integer.parseInt(String.valueOf(objectMap.get("roomNum")));
                            }
                            if (null != objectMap.get("parkingNum")) {
                                parkingNumCount = parkingNumCount + Integer.parseInt(String.valueOf(objectMap.get("parkingNum")));
                            }
                            if (null != objectMap.get("forSaleParkingNum")) {
                                forSaleParkingNumCount = forSaleParkingNumCount + Integer.parseInt(String.valueOf(objectMap.get("forSaleParkingNum")));
                            }
                            if (null != objectMap.get("sumHouse")) {
                                houseCommodityValueCount = houseCommodityValueCount.add(new BigDecimal(String.valueOf(objectMap.get("sumHouse"))));
                            }
                            if (null != objectMap.get("sumParkingSaling")) {
                                parkingValueCount = parkingValueCount.add(new BigDecimal(String.valueOf(objectMap.get("sumParkingSaling"))));
                            }
                            if (null != objectMap.get("sumParkingForsale")) {
                                forSaleParkingValueCount = forSaleParkingValueCount.add(new BigDecimal(String.valueOf(objectMap.get("sumParkingForsale"))));
                            }

                            BigDecimal saleArea = StrUtils.isEmpty(valueString) ? BigDecimal.ZERO : new BigDecimal(valueString);
                            saleAreaCount = saleAreaCount.add(saleArea);
                        }
                    }
                }
            }
            //总货值
            totalValue = houseCommodityValueCount.add(parkingValueCount);
            //查询权益比例
            MdmProjectPatner projectPatner = projectBasicService.selecteQuityRatio(projectId);
            if (null != projectPatner.getEquityRatio()) {
                //计算权益货值
                BigDecimal divide = projectPatner.getEquityRatio().divide(new BigDecimal("100"), 4, BigDecimal.ROUND_HALF_UP);
                quityValue = totalValue.multiply(divide);
            }
            //房源均价
            if (null != saleAreaCount && saleAreaCount.compareTo(BigDecimal.ZERO) != 0) {
                houseAvg = houseCommodityValueCount.divide(saleAreaCount, 4, BigDecimal.ROUND_HALF_UP);
            }
            //可售车位均价
            BigDecimal parkingNumCountDec = new BigDecimal(parkingNumCount);
            if (null != Integer.valueOf(parkingNumCount) && parkingNumCountDec.compareTo(BigDecimal.ZERO) != 0) {
                parkingAvg = parkingValueCount.divide(parkingNumCountDec, 4, BigDecimal.ROUND_HALF_UP);
            }
            //未推售车位均价
            BigDecimal forSaleParkingNumCountDec = new BigDecimal(forSaleParkingNumCount);
            if (null != forSaleParkingNumCountDec && forSaleParkingNumCountDec.compareTo(BigDecimal.ZERO) != 0) {
                forSaleParkingAvg = forSaleParkingValueCount.divide(forSaleParkingNumCountDec, 4, BigDecimal.ROUND_HALF_UP);
            }
        }

        content.setRoomNumCount(roomNumCount);
        content.setParkingNumCount(parkingNumCount);
        content.setForSaleParkingNumCount(forSaleParkingNumCount);
        content.setHouseCommodityValueCount(houseCommodityValueCount);
        content.setParkingValueCount(parkingValueCount);
        content.setForSaleParkingValueCount(forSaleParkingValueCount);
        content.setSaleAreaCount(saleAreaCount);
        content.setTotalValue(totalValue);
        content.setQuityValue(quityValue);
        content.setHouseAvg(houseAvg);
        content.setParkingAvg(parkingAvg);
        content.setForSaleParkingAvg(forSaleParkingAvg);

        String typeName = null;
        if (type.equals(CollectTypeEnum.ADJUST_BEFORE.getKey())) {
            typeName = CollectTypeEnum.ADJUST_BEFORE.getValue();
        } else {
            typeName = CollectTypeEnum.ADJUST_AFTER.getValue();
        }
        versionVO.setVersionName(typeName);
        versionVO.setContentVO(content);
        return versionVO;
    }

    private boolean isValidVersionStage(VersionTypeCountDto versionTypeCountDto) {
        return versionTypeCountDto.getVersionState().equals(VersionStatusEnum.SYSGENERATION.getKey()) ||
                versionTypeCountDto.getVersionState().equals(VersionStatusEnum.SUCCESSAPPROVED.getKey());
    }

    private ValueReviewVersionVO prepareVersionData(String projectId, String type, MdmProjectPatner projectPatner) {
        //版本对象（封装版本和对应的数据）
        ValueReviewVersionVO versionVO = new ValueReviewVersionVO();
        //详情对象（用于封装数据）
        ValueReviewVersionContentVO content = new ValueReviewVersionContentVO();
        //转换versionName为中文
        String typeName = null;
        if (type.equals(CollectTypeEnum.CASTDECISION.getKey())) {
            typeName = CollectTypeEnum.CASTDECISION.getValue();
        } else if (type.equals(CollectTypeEnum.WARPLAN.getKey())) {
            typeName = CollectTypeEnum.WARPLAN.getValue();
        } else {
            typeName = CollectTypeEnum.GETPRICE.getValue();
        }
        //计算返回的数值
        //定义总房源数
        int roomNumCount = 0;
        //定义可售车位数
        int parkingNumCount = 0;
        //定义未推售车位数
        int forSaleParkingNumCount = 0;
        //定义房源货值
        BigDecimal houseCommodityValueCount = BigDecimal.ZERO;
        //定义未推售车位货值
        BigDecimal forSaleParkingValueCount = BigDecimal.ZERO;
        //定义可售车位货值
        BigDecimal parkingValueCount = BigDecimal.ZERO;
        //定义总面积
        BigDecimal saleAreaCount = BigDecimal.ZERO;
        //总货值
        BigDecimal totalValue = BigDecimal.ZERO;
        //权益货值
        BigDecimal quityValue = BigDecimal.ZERO;
        //房源均价
        BigDecimal houseAvg = BigDecimal.ZERO;
        //可售车位均价
        BigDecimal parkingAvg = BigDecimal.ZERO;
        //未推售车位均价
        BigDecimal forSaleParkingAvg = BigDecimal.ZERO;

        List<PriceValueOrg> priceValueOrgList = submitApprovedProjectService.selectPriceValueOrgList(projectId, type);
        if (CollectionUtils.isNotEmpty(priceValueOrgList)) {
            for (PriceValueOrg priceValueOrgs : priceValueOrgList) {
                String valueString = priceVersionService.selectArea(priceValueOrgs.getVersionId(), type);
                //总房源数
                Integer roomNum = priceValueOrgs.getRoomNum();
                if (null != roomNum) {
                    roomNumCount = roomNumCount + roomNum;
                } else {
                    roomNumCount = roomNumCount + 0;
                }
                //可售车位数
                Integer parkingNum = priceValueOrgs.getParkingNum();
                if (null != parkingNum) {
                    parkingNumCount = parkingNumCount + parkingNum;
                } else {
                    parkingNumCount = parkingNumCount + 0;
                }
                //未推售车位数
                Integer forsaleParkingNum = priceValueOrgs.getForsaleParkingNum();
                if (null != forsaleParkingNum) {
                    forSaleParkingNumCount = forSaleParkingNumCount + forsaleParkingNum;
                } else {
                    forSaleParkingNumCount = forSaleParkingNumCount + 0;
                }
                //房源货值
                BigDecimal houseCommodityValue = priceValueOrgs.getHouseCommodityValue();
                if (null != houseCommodityValue) {
                    houseCommodityValueCount = houseCommodityValueCount.add(houseCommodityValue);
                } else {
                    houseCommodityValueCount = houseCommodityValueCount.add(BigDecimal.ZERO);
                }
                //未推售车位货值
                BigDecimal commodityValue = priceValueOrgs.getCommodityValue();
                if (null != commodityValue) {
                    forSaleParkingValueCount = forSaleParkingValueCount.add(commodityValue);
                } else {
                    forSaleParkingValueCount = forSaleParkingValueCount.add(BigDecimal.ZERO);
                }
                //可售车位货值
                BigDecimal notCommodityValue = priceValueOrgs.getNotCommodityValue();
                if (null != notCommodityValue) {
                    parkingValueCount = parkingValueCount.add(notCommodityValue);
                } else {
                    parkingValueCount = parkingValueCount.add(BigDecimal.ZERO);
                }
                //总面积

                BigDecimal saleArea = StrUtils.isEmpty(valueString) ? BigDecimal.ZERO : new BigDecimal(valueString);
                saleAreaCount = saleAreaCount.add(saleArea);
            }
            //总货值
            totalValue = houseCommodityValueCount.add(parkingValueCount);
            if (null != projectPatner.getEquityRatio()) {
                //计算权益货值
                BigDecimal divide = projectPatner.getEquityRatio().divide(new BigDecimal("100"), 4, BigDecimal.ROUND_HALF_UP);
                quityValue = totalValue.multiply(divide);
            }
            //房源均价
            if (null != saleAreaCount && saleAreaCount.compareTo(BigDecimal.ZERO) != 0) {
                houseAvg = houseCommodityValueCount.divide(saleAreaCount, 4, BigDecimal.ROUND_HALF_UP);
            }
            //可售车位均价
            BigDecimal parkingNumCountDec = new BigDecimal(parkingNumCount);
            if (null != parkingNumCountDec && parkingNumCountDec.compareTo(BigDecimal.ZERO) != 0) {
                parkingAvg = parkingValueCount.divide(parkingNumCountDec, 4, BigDecimal.ROUND_HALF_UP);
            }
            //未推售车位均价
            BigDecimal forSaleParkingNumCountDec = new BigDecimal(forSaleParkingNumCount);
            if (null != forSaleParkingNumCountDec && forSaleParkingNumCountDec.compareTo(BigDecimal.ZERO) != 0) {
                forSaleParkingAvg = forSaleParkingValueCount.divide(forSaleParkingNumCountDec, 4, BigDecimal.ROUND_HALF_UP);
            }
        }
        content.setRoomNumCount(roomNumCount);
        content.setParkingNumCount(parkingNumCount);
        content.setForSaleParkingNumCount(forSaleParkingNumCount);
        content.setHouseCommodityValueCount(houseCommodityValueCount);
        content.setParkingValueCount(parkingValueCount);
        content.setForSaleParkingValueCount(forSaleParkingValueCount);
        content.setSaleAreaCount(saleAreaCount);
        content.setTotalValue(totalValue);
        content.setQuityValue(quityValue);
        content.setHouseAvg(houseAvg);
        content.setParkingAvg(parkingAvg);
        content.setForSaleParkingAvg(forSaleParkingAvg);

        versionVO.setVersionName(typeName);
        versionVO.setContentVO(content);
        return versionVO;
    }

    //#################货值审批差异概览 重构 -2020-04-20######################################################

    private boolean saveLog(String module, String title, String content) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String userName = getOperator().getAlias();
        SysLogBO bo = new SysLogBO();
        bo.setEvent(LogEventEnum.BROWSE);
        bo.setSource(LogSrcEnum.PC);
        bo.setIp(WebUtils.getIpAddr(request));
        bo.setUrl(WebUtils.getUrl(request));
        bo.setModule(module);
        bo.setTitle(title);
        bo.setContent(content);
        bo.setType(LogTypeEnum.ZERO.getKey());
        bo.setIsSuccess(IsSuccessEnum.SUCCESS.getKey());
        return sysLogService.add(bo, userName);
    }


    @Override
    public R saveSupervise(String apiVersion, PriceApproveWarnSaveReqParam param) {
        IdmUser user = getOperator();
        approvalWarningSuperviseService.saveSuperviseInfo(user, param);
        return ok();
    }

    @Override
    public R cancelSupervise(String apiVersion, PriceApproveWarnCancelReqParam param) {
        IdmUser user = getOperator();
        approvalWarningSuperviseService.cancelSupervise(user, param);
        return ok();
    }

    @Override
    public R generatePriceVersionGroup(String apiVersion, String projectId, String flowId, Integer isPresident) {
        priceVersionGroupService.generatePriceVersionGroup(projectId, flowId, isPresident);
        return ok();
    }

	@Override
	public R createPriceVersionGroup(String apiVersion, String projectId, String schemeId) {
		priceVersionGroupService.createPriceVersionGroup(schemeId, projectId);
		return ok();
	}

}
